package drds.global_transaction.impl;


import com.caucho.hessian.server.HessianServlet;
import drds.common.$;
import drds.dbutils.native_sql.Db;
import drds.dbutils.tools.DbUtils;
import drds.dbutils.tools.MapListBuilder;
import drds.global_transaction.BranchTransactionInfo;
import drds.global_transaction.DataSourceFactory;
import drds.global_transaction.TransactionIdFactory;
import drds.global_transaction.TransactionService;
import drds.global_transaction.table.branch_transaction;
import drds.global_transaction.table.global_transaction;
import lombok.extern.slf4j.Slf4j;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Slf4j
public class TransactionServiceImpl extends HessianServlet implements TransactionService
{
    @Override
    public String registertGlobalTransaction() throws Exception
    {
        String globalTransactionId = TransactionIdFactory.createTransactionId();

        String sql = "INSERT INTO `global_transaction` ( `global_transaction_id`, `status`, `rollback_type`, `create_date_time`, `create_date_time_long`, `update_date_time`, `update_date_time_long`) VALUES " +
                "( ?, ?, ?, ?, ?, ?, ?)";
        DataSource dataSource = DataSourceFactory.getDataSource();
        Connection connection = dataSource.getConnection();
        List<Object> objectList = new ArrayList<Object>();
        objectList.add(globalTransactionId);
        objectList.add(global_transaction.status_init);
        objectList.add(global_transaction.rollback_type_not_init);
        Date nowDate = new Date();
        objectList.add(nowDate);
        objectList.add(nowDate.getTime());
        objectList.add(nowDate);
        objectList.add(nowDate.getTime());
        //
        try
        {
            Db.insertWithReturnPrimaryKeyValue(connection, sql, objectList.toArray());
        } catch (SQLException e)
        {
            log.error($.printStackTraceToString(e));
            throw e;
        } finally
        {
            DbUtils.close(connection);
        }
        return globalTransactionId;
    }

    @Override
    public BranchTransactionInfo registerBranchTransaction(String globalTransactionId) throws Exception
    {

        String branch_transaction_id = TransactionIdFactory.createTransactionId();

        String sql = "INSERT INTO `branch_transaction` ( `global_transaction_id`, `branch_transaction_id`, `status`, `create_date_time`, `create_date_time_long`, `update_date_time`, `update_date_time_long`) VALUES " +
                "(?, ?, ?, ?, ?, ?, ?)";
        DataSource dataSource = DataSourceFactory.getDataSource();
        Connection connection = dataSource.getConnection();
        List<Object> objectList = new ArrayList<Object>();
        objectList.add(globalTransactionId);
        objectList.add(branch_transaction_id);
        objectList.add(branch_transaction.status_created);
        Date nowDate = new Date();
        objectList.add(nowDate);
        objectList.add(nowDate.getTime());
        objectList.add(nowDate);
        objectList.add(nowDate.getTime());
        //
        long create_date_time_long = 0;
        int branchTransactionTimeout = 0;
        try
        {
            Db.insertWithReturnPrimaryKeyValue(connection, sql, objectList.toArray());
            //
            sql = "SELECT create_date_time_long from global_transaction where global_transaction_id=?";
            ResultSet resultSet = Db.query(connection, sql, new Object[]{globalTransactionId});
            create_date_time_long = (long) MapListBuilder.get(resultSet, "create_date_time_long");

            //根据主键进行查询分支事务超时值,分支事务需要在每次执行的时候进行比较当前的时间是否已经超时。
            sql = "select id,branch_transaction_timeout,global_transaction_timeout from global_transaction_config where id=1";
            resultSet = Db.query(connection, sql);
            branchTransactionTimeout = (int) MapListBuilder.get(resultSet, "branch_transaction_timeout");
        } catch (SQLException e)
        {
            log.error($.printStackTraceToString(e));
            throw e;
        } finally
        {
            DbUtils.close(connection);
        }
        BranchTransactionInfo branchTransactionInfo = new BranchTransactionInfo();
        branchTransactionInfo.setGlobalTransactionId(globalTransactionId);
        branchTransactionInfo.setBranchTransactionId(branch_transaction_id);
        branchTransactionInfo.setGlobalTransactionCreateDateTimeLong(create_date_time_long);
        branchTransactionInfo.setBranchTransactionTimeout(branchTransactionTimeout);
        return branchTransactionInfo;
    }
    /**
     * 需要保存到数据库里面,id,createTime,超时时间和状态,rollbackType 1分支事务异常2全局事务超时自动监听
     */
    //创建分支事务
    //id,createDateTime,status
    //更新分支事务成功或者失败，如果是失败则需要进行全局事务的回滚.
    //定时任务首先在系统启动的时候，通知各个业务进行事务回滚。
    //然后设置超时.
    //全局超时和分支事务携带的超时条件存在一个时间的间隔。也就是说分支事务每次都需要获取全局事务的创建时间  然后系统判断超时如果在分支事务的时候进行超时，那么给全局事务一个分支超时回滚。
    //这样就可以比较系统超时和分支超时两个地方处理不急的问题。
    //这里有个问题 要是系统出现一个RM操作失败的情况怎么办。那么则需要处理的时候尽可能的快。
}
